package vh.sphynx.runtime.interpreter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.util.EList;

import vh.sphynx.runtime.ExecutionContext;
import vh.sphynx.runtime.SphynxInterpreter;
import vh.sphynx.sphynx.XExpression;
import vh.sphynx.sphynx.XLiteral;
import vh.sphynx.sphynx.impl.XArrayImpl;
import vh.sphynx.sphynx.impl.XBoolLiteralImpl;
import vh.sphynx.sphynx.impl.XDataFrameImpl;
import vh.sphynx.sphynx.impl.XIntLiteralImpl;
import vh.sphynx.sphynx.impl.XJavaTypeImportImpl;
import vh.sphynx.sphynx.impl.XNullLiteralImpl;
import vh.sphynx.sphynx.impl.XStringLiteralImpl;
import vh.sphynx.util.HashMapEx;
import vh.sphynx.util.ReflectionUtil;
import vh.sphynx.util.SphynxNullReferenceExpcetion;

public class XLiteralInterpreter {
	
	public static Object _evaluate(SphynxInterpreter interpreter, XIntLiteralImpl lit, ExecutionContext context) {
		return lit.getValue();
	}
	
	public static Object _evaluate(SphynxInterpreter interpreter, XStringLiteralImpl lit, ExecutionContext context) {
		return lit.getValue();
	}
	
	public static Object _evaluate(SphynxInterpreter interpreter, XBoolLiteralImpl lit, ExecutionContext context) {
		return lit.isIsTrue();
	}
	
	public static Object _evaluate(SphynxInterpreter interpreter, XNullLiteralImpl lit, ExecutionContext context) {
		return null;
	}
	
	//TODO: test
	public static Object _evaluate(SphynxInterpreter interpreter, XArrayImpl array, ExecutionContext context) {
		if (array.isList()) {
			List<Object> list = new ArrayList<Object>(array.getExpressions().size());
			for (XExpression exp: array.getExpressions())
				list.add(interpreter.resolveValue(exp, context));
			return list;
		}
		else if (array.isMap()) {
			Map<Object, Object> map = new HashMap<Object, Object>();
			EList<XLiteral> keys = array.getKeys();
			for(int i = 0; i < keys.size(); i++) {
				Object keyValue = interpreter.resolveValue(keys.get(i), context);
				if (keyValue == null)
					throw new SphynxNullReferenceExpcetion(context, array);
				Object value = interpreter.resolveValue(array.getExpressions().get(i), context);
				map.put(keyValue, value);
			}
			return map;
		}
		else {
			Object list[] = new Object[array.getExpressions().size()];
			EList<XExpression> exps = array.getExpressions();
			for (int i = 0; i < exps.size(); i++)
				list[i] = interpreter.resolveValue(exps.get(i), context);
			return list;
		}
	}
	
	public static Object _evaluate(SphynxInterpreter interpreter, XDataFrameImpl array, ExecutionContext context) {
		Map<Object, Object> map = new HashMapEx(array.isExtensible(), array.isReadonly(), context);
		EList<String> keys = array.getKeys();
		for(int i = 0; i < keys.size(); i++) {
			String keyValue = keys.get(i);
			Object value = interpreter.resolveValue(array.getExpressions().get(i), context);
			map.put(keyValue, value);
		}
		return map;
	}
	
	private static Map<XJavaTypeImportImpl, Class<?>> importedClasses = new HashMap<XJavaTypeImportImpl, Class<?>>(); 
	
	public static Object _evaluate(SphynxInterpreter interpreter, XJavaTypeImportImpl classImport, ExecutionContext context) {
		Object value = importedClasses.get(classImport);
		if (value == null) {
			value = ReflectionUtil.getClass(classImport.getClass_());
			if (value != null)
				importedClasses.put(classImport, (Class<?>) value);
		}
		return value;
	}

}
